package cn.com.bluemoon.daps.system.controller;


import cn.com.bluemoon.daps.common.constant.DapConstant;
import cn.com.bluemoon.daps.common.datascope.BmPermission;
import cn.com.bluemoon.daps.common.datascope.IgnorePermission;
import cn.com.bluemoon.daps.common.datascope.log.OperateLog;
import cn.com.bluemoon.daps.common.datascope.log.enums.ModuleObject;
import cn.com.bluemoon.daps.common.datascope.log.enums.OperateType;
import cn.com.bluemoon.daps.common.datascope.log.holder.ProcessLogHolder;
import cn.com.bluemoon.daps.common.domain.FeignApiRespBean;
import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.common.domain.UserInfoHolder;
import cn.com.bluemoon.daps.common.toolkit.BmAssetUtils;
import cn.com.bluemoon.daps.domp.api.IDompService;
import cn.com.bluemoon.daps.domp.api.LocalDompService;
import cn.com.bluemoon.daps.domp.api.LocalUserService;
import cn.com.bluemoon.daps.domp.api.UserService;
import cn.com.bluemoon.daps.system.entity.DapSystemLogin;
import cn.com.bluemoon.daps.system.service.DapSystemLoginService;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.google.common.collect.ImmutableMap;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 独立系统登录&权限信息入口
 * </p>
 *
 * @author admin
 * @since 2020-08-04
 */
@Api(tags = {"独立系统登录&权限信息入口"})
@RestController
@Slf4j
@RequestMapping
public class DapController {
    @Resource
    private LocalUserService userService;

    @Resource
    private LocalDompService dompService;

    @Resource
    private DapSystemLoginService systemLoginService;

    @PostMapping("/user/getToken")
    @IgnorePermission(name = "登录接口功能，改接口前需要先登录一下蓝数通~~（测试环境使用）")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "返回token", response = ResultBean.class)})
    public ResultBean<Map<String, Object>> loginPreGetToken(@RequestParam("username") String username,
                                                            @RequestParam("password") String password) {
        // 无法直接拿去token则进行用户登录操作（优先登录蓝数通获取token，若失败，尝试去门户接口（最终走门户）进行获取token
        ResultBean<Map<String, Object>> resp = login(username, password, "");
        if (resp.isOk()) {
            Map<String, Object> respMap = resp.getContent();
            String token = Objects.toString(respMap.get("token"), "");
            if (StringUtils.isBlank(token)) {
                return ResultBean.error("测试独立入口登录前，请先登录测试环境蓝数通获取token信息");
            }
        }
        return resp;
    }


    @PostMapping("/login")
    @IgnorePermission(name = "登录接口功能")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "返回token", response = ResultBean.class)})
    public ResultBean<Map<String, Object>> login(@RequestParam("username") String username,
                                                 @RequestParam("password") String password,
                                                 @RequestParam("captcha") String captcha) {
        // 直接用用户id尝试拿去有效的token然后返回
        String token = "";

        // 优先使用蓝数通的测试登录入口
        final String user = StrUtil.trim(username);
        BmAssetUtils.isTrue(NumberUtil.isNumber(user), "员工账号必须为正整数");
        FeignApiRespBean<String> reqBody_ = dompService.dompLogin(username, password,null);
        if ("200".equals(reqBody_.getRespCode()) && StringUtils.isNotBlank(reqBody_.getToken())){
            token = reqBody_.getToken();
            log.info("通过登录蓝数通获取token成功");
            systemLoginService.upsert(username, password, token);
            return ResultBean.ok(ImmutableMap.of("token", token));
        }
        return null;
    }

    /**
     * // 退出用户存在问题，目前没有微服务接口进行退出
     * 需要独立维护portal提供的token，独立维护有效时间
     *
     * @return ok
     * @since 2020年10月29日 确认，门户SSO没有提供系统退出，需要自己独立维护token过期
     * <em>另外，SSO提供的token是UUID，多次登录多次的token都是有效的！！！要是独立维护他们的token就会导致数量暴炸！！</em>
     * 方案：{@link DapConstant.VersionMark#SYSTEM_PERMISSION_MARK}
     * 解决点击退出，直接给一个自定义的token，然后前端需要重新赋值浏览器的token值，为了使后续的请求头携带的token都是无效的
     * 进而需要用户登录后才可以访问，避免独自维护每个token的有效时间
     */
    @PostMapping("/logout")
    @BmPermission(value = "logout", name = "退出系统", queryTokenPerm = true, ignore = true)
    @OperateLog(type = OperateType.OTHERS, moduleName = ModuleObject.SYSTEM, menuName = "登出系统", detail = "用户登录平台")
    public ResultBean<ImmutableMap<String, String>> logout(@RequestParam(DapConstant.WEB_HTTP_TOKEN_NAME) String token) {
        String logoutToken = IdWorker.getIdStr();
        UserInfoHolder.UserInfo userInfo = UserInfoHolder.getUserInfoOrEmpty();
        log.info("用户{}触发退出，返回一个新的自定义token{}给浏览器，进而使后续请求token无效", userInfo.getAccount(), logoutToken);
        ProcessLogHolder.append("用户["+userInfo.getAccount()+"]退出系统");
        ImmutableMap<String, String> of = ImmutableMap.of(DapConstant.WEB_HTTP_TOKEN_NAME, logoutToken);
        return ResultBean.ok(of);
    }

    @PostMapping("/menus")
    @BmPermission(value = "getMenus", name = "获取菜单信息", queryTokenPerm = true, ignore = true)
    @ApiResponses(value = {@ApiResponse(code = 200, message = "菜单", response = ResultBean.class)})
    @OperateLog(type = OperateType.SELECT, moduleName = ModuleObject.SYSTEM, menuName = "系统菜单信息", detail = "用户登录平台")
    public ResultBean<Map<String, List<LocalDompService.MenuDto>>> menus(@RequestParam(DapConstant.WEB_HTTP_TOKEN_NAME) String token) {
        String userId = userService.isLoginUser(token);
        ProcessLogHolder.append("用户["+userId+"]登入，获取菜单列表");
        Map<String, List<LocalDompService.MenuDto>> reqBody = dompService.getMenuPathByTokenAndUserId(token, userId);
        systemLoginService.upsertByUserInfoHolder();
        return ResultBean.ok(reqBody);
    }

    @GetMapping("/userInfo")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "用户信息", response = ResultBean.class)})
    @BmPermission(value = "getUserInfo", name = "获取用户信息", queryTokenPerm = true, ignore = true)
    public ResultBean<List<Map<String, Object>>> userInfo(@RequestParam(DapConstant.WEB_HTTP_TOKEN_NAME) String token) {
        String userId = userService.isLoginUser(token);
        List<Map<String, Object>> userInfoById = userService.getUserInfoById(userId);
        systemLoginService.upsertByUserInfoHolder();
        return ResultBean.ok(userInfoById);
    }

    @GetMapping("/user/list")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "获取访问过当前系统用户信息", response = ResultBean.class)})
    @BmPermission(value = "getPV", name = "获取访问过当前系统用户信息", ignore = true)
    public ResultBean<Map<String, DapSystemLogin>> userList() {
        List<DapSystemLogin> list = systemLoginService.list(systemLoginService.bmLambdaQuery());
        // 屏蔽安全字段对外
        Map<String, DapSystemLogin> map = list.stream().map(d -> {
            d.setToken(null);
            d.setPassword(null);
            return d;
        }).collect(Collectors.toMap(DapSystemLogin::getAccount, d -> d, (a, b) -> b));
        systemLoginService.upsertByUserInfoHolder();
        return ResultBean.ok(map);
    }

}
